package typistcal.commandlogic;

import java.util.InputMismatchException;

import typistcal.exception.WrongTimeFormatException;
import typistcal.userinterface.UserInterface;

//@author A0105620X
public class Event {
	
	public String startTime, endTime;
	public String startDate, endDate;
	public String label;
	public EventType eventType;
	private String eventStatus;
	private String duration = "default";
	private String labelQuoted = "";
	
	public String fieldKeyword,eventKeyword;
	public String toKeyword;
	public int[] lineNumber;
	private static final String[] LIST_FIELD = { "label", "status", "end",
		"deadline", "start", "time", "date" };
	
	private UserPreference up;
	private final int TIME = 0, DATE = 1;

	public enum EventType {
		SCHEDULED, DEADLINE, TODO
	};

	public Event(String userInput, CommandType commandType) {
		up = UserPreference.getUserPreference();
		
		switch(commandType){
		case ADD_INFO:
			createEventForAdd(userInput);
			break;
		case DELETE_INFO: case SHOW_INFO: case FIND_INFO:
			createEventForSearch(userInput);
			break;
		case UPDATE_INFO:
			createEventForUpdate(userInput);
		default:
		}
	}

	private void createEventForUpdate(String userInput) {
		fieldKeyword = "";
		for (int i = 0; i < LIST_FIELD.length; i++) {
			if (userInput.toLowerCase().contains(LIST_FIELD[i])) {
				fieldKeyword = LIST_FIELD[i];
				break;
			}
		}
		if (fieldKeyword.isEmpty()) {
			if (userInput.toLowerCase().contains(" to ")) {

				fieldKeyword = "label";
				String[] tokens = userInput.split(" to ");
				eventKeyword = tokens[0];
				toKeyword = tokens[1];
			} else {
				
				determineStatusAndEventKeyword(userInput);
				
				
			}
		} else {
			String[] tokens = userInput.split(fieldKeyword);
			eventKeyword = tokens[0].trim().toLowerCase();
			toKeyword = tokens[1].trim();
		}
		createEventForSearch(eventKeyword);

		boolean isDecoded = false;
		do {
			try {
				decodeToKeyword();
				isDecoded = true;
			} catch (WrongTimeFormatException e) {
				toKeyword = UserInterface.displayAndAskForFeedback(e
						.getMessage()
						+ "\nPlease modify your time/date format.");
			}
		} while (!isDecoded);

	}

	private void determineStatusAndEventKeyword(String userInput) {
		fieldKeyword = "status";
		String[] tokens = userInput.trim().split(" ");
		String lastWord = tokens[tokens.length - 1];
		toKeyword = determineStatus(lastWord);
		eventKeyword = userInput.substring(0, userInput.trim().lastIndexOf(" "));
	}

	private String determineStatus(String lastWord) {
		if (EventKeyword.isComplete(lastWord)) {
			return "Completed";
		} else if (EventKeyword.isIncomplete(lastWord)) {
			return "Incomplete";
		} else {
			throw new InputMismatchException(
					"invalid format for update");
		}
	}

	private void decodeToKeyword() throws WrongTimeFormatException {
		switch (fieldKeyword) {
		case "end":
		case "deadline":
		case "start":
			this.fieldKeyword = formatDateAndTime(fieldKeyword, toKeyword);
			break;
		case "time":
			toKeyword = TimeUtility.parseTime(toKeyword);
			break;
		case "date":
			toKeyword = TimeUtility.parseDate(toKeyword);
			break;
		case "label":
			break;
		case "status":
			toKeyword = determineStatus(toKeyword);
		default:
		}
	}
	
	private String formatDateAndTime(String fieldKeyword, String toKeyword)
			throws WrongTimeFormatException {
		String[] TD = { endTime, endDate };
		
		String type = fieldKeyword;

		if (toKeyword.toLowerCase().contains("time")) {
			toKeyword = toKeyword.replaceAll("(?i)time", "").trim();
			TD[TIME] = TimeUtility.parseTime(toKeyword);
			fieldKeyword = fieldKeyword.concat("time");

		} else if (toKeyword.toLowerCase().contains("date")) {
			toKeyword = toKeyword.replaceAll("(?i)date", "").trim();
			TD[DATE] = TimeUtility.parseDate(toKeyword);
			fieldKeyword = fieldKeyword.concat("date");
		} else {
			determineDateAndTime(toKeyword, fieldKeyword);
		}
		assignStartOrEnd(type, TD);

		return fieldKeyword;
	}

	private void createEventForSearch(String userInput) {
		endTime = "";
		endDate = "";
		String LabelQuoted = "";
		eventKeyword = userInput;

		if (!determineLineNumber(userInput)) {

			userInput = extractQuotedContent(userInput);

			try {
				// support only time point, not duration
				determineDateAndTime(userInput, "end");
				if (!endTime.isEmpty() && !endTime.isEmpty()) {
					if (!endTime.trim().equals("00:00")
							&& !endTime.trim().equals("23:59")) {
						eventKeyword = endDate.concat(" " + endTime);
					} else {
						eventKeyword = endDate;
					}
				} else if (!endTime.isEmpty()) {
					eventKeyword = endTime;
				} else if (!endDate.isEmpty()) {
					eventKeyword = endDate;
				}
			} catch (WrongTimeFormatException e) {
				try{
					eventKeyword = determineStatus(userInput);
				}catch(InputMismatchException e1){
					recoverQuotedContentForSearch(LabelQuoted);
				}
			}
		}
	}

	private void recoverQuotedContentForSearch(String LabelQuoted) {
		eventKeyword = eventKeyword.replaceFirst("RESERVEDQUOTEDLABEL",
				LabelQuoted).replaceAll("\"", "");
	}

	private boolean determineLineNumber(String userInput) {
		
		String tokens[] = userInput.trim().replaceAll(" +", " ").split(" ");
		lineNumber = new int[tokens.length];
		boolean isLineNumberList = true;

		for (int i = 0; i < tokens.length&&isLineNumberList; i++) {
			try {
				lineNumber[i] = Integer.parseInt(tokens[i]);
			} catch (NumberFormatException e) {
				isLineNumberList = false;
				lineNumber[0]=-1;
			}
		}
		return isLineNumberList;
	}

	private void createEventForAdd(String userInput) {
		eventStatus = "Incomplete";
		
		userInput = extractQuotedContent(userInput);

		determineEventType(userInput.replaceAll(" +", " "));

		switch (eventType) {
		case SCHEDULED:
			createScheduledEvent(userInput);
			break;
		case DEADLINE:
			createDeadlineEvent(userInput);
			break;
		default:
			createTodoEvent(userInput);
			break;
		}
		
		recoverQuotedContent();
		
		if(label.isEmpty()){
			label = UserInterface.displayAndAskForFeedback("No task label detected, please input your label");
		}
	}

	private String extractQuotedContent(String userInput) {
		if(userInput.matches(".*\".*\".*")){
			int firstQuote=userInput.indexOf("\"");
			int lastQuote = userInput.indexOf("\"", firstQuote+1);
			labelQuoted = userInput.substring(firstQuote, lastQuote+1);
			userInput = userInput.replaceAll(labelQuoted, "RESERVEDQUOTEDLABEL");
		}
		return userInput;
	}
	
	private void recoverQuotedContent() {
		if(label.trim().equals("RESERVEDQUOTEDLABEL")){
			label = label.replaceFirst("RESERVEDQUOTEDLABEL",labelQuoted.substring(1, labelQuoted.length()-1));
		}else{
			label = label.replaceFirst("RESERVEDQUOTEDLABEL",labelQuoted);
		}
	}
	
	private void determineEventType(String input) {
		if (containsDeadlineIndicator(input)) {
			eventType = EventType.DEADLINE;
		} else {
			eventType = EventType.SCHEDULED;
		}
	}

	private boolean containsDeadlineIndicator(String input) {
		return input.toLowerCase().contains("by ")
				|| input.toLowerCase().contains("before ")
				|| input.toLowerCase().contains("due ")
				|| input.toLowerCase().contains("deadline ")
				|| input.toLowerCase().contains("finish ")				
				|| input.toLowerCase().contains("complete ");
	}

	private void createScheduledEvent(String userInput) {
		String userInputCopy = userInput;
		userInput = extractDuration(userInput);

		String delim = findDelimiterForStartAndEnd(userInput);
		decodeEventWithDelimiter(userInput, delim);

		if (label.equals("CANTDECODE")) {
			label = userInputCopy;
			if (duration.equals("default")) {
				eventType = EventType.TODO;
			} else {
				startDate = setDefaultDate("start");
				startTime = setDefaultTime("start", startDate);
				computeEndDate(duration);
				updateToValidScheduleIfNot();
			}
		} else {
			computeEndDate(duration);
			updateToValidScheduleIfNot();
		}
	}
	
	private String extractDuration(String userInput) {
		if (userInput.toLowerCase().matches(".* for \\d.*$")) {

			duration = userInput.substring(userInput.toLowerCase().lastIndexOf(
					" for "));
			userInput = userInput.substring(0, userInput.toLowerCase()
					.lastIndexOf(" for "));
			while (!duration.toLowerCase().matches(".* for \\d.*$")) {

				duration = userInput.substring(
						userInput.toLowerCase().lastIndexOf(" for ")).concat(
						duration);
				userInput = userInput.substring(0, userInput.toLowerCase()
						.lastIndexOf(" for "));

			}
			duration = duration.replaceFirst("(?i)for ", "");
			String[] tokens = duration.trim().replaceAll(" +", " ").split(" ");
			String durationCopy = duration;
			if (tokens.length >= 2) {
				try {
					Integer.parseInt(tokens[0]);
					duration = tokens[0].concat(" " + tokens[1]);
				} catch (NumberFormatException e) {
					duration = tokens[0];
				}
				userInput = userInput.concat(" "
						+ durationCopy.replaceFirst(duration, ""));
			}
		}
		return userInput;
	}
	
	private String findDelimiterForStartAndEnd(String userInput) {
		String delim;
		
		final String delim_dash = "-";
		final String delim_to = " to "; 
		
		if (userInput.contains("-")) {
			delim = delim_dash;
		}else if (userInput.toLowerCase().contains(" to ")) {
			delim = delim_to;
		}else{
			delim = "";
		}
		return delim;
	}

	private void decodeEventWithDelimiter(String userInput, String delim) {
		String startInput = userInput;
		String endInput = "";

		if (!delim.isEmpty()) {
			for (int i = 0; i < userInput.length();) {
				i = "  ".concat(userInput).indexOf(delim, i + 1);

				if (i == -1) {
					break;
				} else {
					String[] tokens = userInput.substring(i-2 + delim.length()).trim()
							.split(" ");
					if(isDateOrTime(tokens)) {
						startInput = userInput.substring(0, i -2).trim();
						endInput = userInput.replaceFirst(startInput,"").replaceFirst(delim, "");
						break;
					}
				}
			}
		}
		
		if(delim.equals("-")&&endInput.isEmpty()&&userInput.contains(" to ")){
			decodeEventWithDelimiter(userInput, " to ");
			return;
		}
		
		String endLabel = decodeStartOrEndTimet(endInput, "end");
		String startLabel = decodeFromTime(startInput);

		if (startLabel.equals("CANTDECODE")) {
			startLabel = decodeStartOrEndTimet(startInput, "start");
		}

		if (startLabel.equals("CANTDECODE") && !endInput.trim().isEmpty()) {
			startDate = setDefaultDate("start");
			startTime = setDefaultTime("start", startDate);
			startLabel = startInput;
		}
		
		label = startLabel.trim().concat(" " + endLabel.trim()).trim();
	}

	
	
	private boolean isDateOrTime(String[] tokens) {
		boolean isDateOrTime = false;
		try{
			TimeUtility.parseDate(tokens[0]);
			isDateOrTime = true;
		}catch(WrongTimeFormatException e){
			try{
				TimeUtility.parseTime(tokens[0]);
				isDateOrTime = true;
			}catch(WrongTimeFormatException e1){
				if(tokens.length>=2){
					try{
						TimeUtility.parseDate(tokens[0]+ " "+ tokens[1]);
						isDateOrTime = true;
					}catch(WrongTimeFormatException e2){
						isDateOrTime = false;
					}
						
				}
			}
		}
		return isDateOrTime;
	}

	private String decodeStartOrEndTimet(String userInput,String type) {
		if(userInput.trim().isEmpty()){
			return "";
		}
		userInput = userInput.replaceAll(" +", " ");
		boolean decoded = false;
		boolean decodedOnce = false;
		String currLabel = userInput;
		String labelDecoded = "CANTDECODE";
		String possibleTime;

		do {
			if (userInput.isEmpty()) {
				break;
			}
			decoded = false;
			String[] tokens = userInput.split(" ");
			String label1 = "";

			for (int i = -1; i < tokens.length && !decoded; i++) {
				if (i != -1) {
					label1 = label1.concat(tokens[i] + " ");
				}
				String label2 = "";
				for (int j = tokens.length; j > i + 1 && !decoded; j--) {

					if (j != tokens.length) {
						label2 = tokens[j].concat(" " + label2);
					}
					currLabel = label1.concat(label2).trim();

					possibleTime = " ".concat(userInput
							.substring(0, userInput.lastIndexOf(label2.trim()))
							.replaceFirst(label1, "").trim());

					try {
						determineDateAndTime(possibleTime, type);
						decoded = true;
						decodedOnce = true;
					} catch (WrongTimeFormatException e) {
						decoded = false;
					}
				}
			}

			userInput = currLabel;
			if (decoded) {
				labelDecoded = currLabel;
			}
		} while (decodedOnce && decoded);

		return labelDecoded.trim();
	}

	private void computeEndDate(String duration) {
		String[] tokens;
		boolean decoded = false;

		if (duration.equals("default")) {
			setDefaultEnding();
			return;
		} else {
			String label2 = "";
			String[] words = duration.replaceAll(" +", "").split(" ");
			for (int j = words.length; j > 0 && !decoded; j--) {

				if (j != words.length) {
					label2 = words[j].concat(" " + label2);
				}
				duration = duration.replaceFirst(label2.trim(), "");

				try {
					tokens = TimeUtility.getEndTime(startDate, startTime,
							duration).split(",");

					assert (tokens.length == 2);
					endDate = tokens[0];
					endTime = tokens[1];
					decoded = true;
				} catch (WrongTimeFormatException e) {
					decoded = false;
				}
			}
		}
		if (!decoded) {
			setDefaultEnding();	
			label = label.concat(" for " + duration);
		}
	}

	private void setDefaultEnding() {
		if (endDate == null || endDate.isEmpty()) {
			endDate = startDate;
		}
		if (endTime == null || endTime.isEmpty()) {
			endTime = "23:59";
		}
	}
	
	private void validateStartDate() {
		if (startTime != null) {
			if (!startTime.equals(TimeUtility.getDateAndTime().replaceAll(
					TimeUtility.getToday(), ""))
					&& startDate.equals(TimeUtility.getToday())) {
				if (endDate != null && !endDate.isEmpty()) {
					startDate = endDate;
				}
			}
		}
	}

	private void updateToValidScheduleIfNot() {
		String userInput;
		
			if (!TimeUtility.isValidStartEndDate(startDate, endDate)) {
				endDate = startDate;
			}

			while (!TimeUtility.isValidSchedule(startDate, startTime, endDate,
					endTime)) {
				userInput = UserInterface
						.displayAndAskForFeedback("Invalid input: "
								+ startDate
								+ " "
								+ startTime
								+ " - "
								+ endDate
								+ " "
								+ endTime
								+ ". \nPress enter key if you want to modify end time, or enter \"x\" for start time");
				try {
					if (userInput.equals("x")) {
						determineDateAndTime(
								UserInterface
										.displayAndAskForFeedback("Please enter the start time."),
								"start");
					} else if (userInput.isEmpty()) {
						determineDateAndTime(
								UserInterface
										.displayAndAskForFeedback("Please enter the end time."),
								"end");
					} else {
						break;
					}
				} catch (WrongTimeFormatException e) {

				}
			}
		
	}

	private String decodeFromTime(String userInput) {
		
		boolean decoded = false;
		boolean decodedOnce = false;

		String currLabel = "";
		String labelDecoded = "CANTDECODE";

		boolean isFromTime = false;
		for (int i = 0; i < userInput.length(); ) {
			i="  ".concat(userInput).indexOf(" from ",i+1);
			
			if(i==-1){
				break;
			}else{		
				String[] tokens = userInput.substring(i-2 + " from ".length()).trim()
						.split(" ");
				isFromTime = isDateOrTime(tokens);
				
				if(isFromTime) {
					userInput = userInput.substring(0,i-1).trim().concat(" "+ userInput.substring(i+"from".length()).trim());
				}
			}
		}
		
		String start;
		start = userInput.replaceAll(" +", " ");
		
		if (isFromTime) {
			do {
				if (userInput.isEmpty()) {
					break;
				}
				decoded = false;
				String[] tokens = userInput.split(" ");
				String label1 = "";

				for (int i = -1; i < tokens.length && !decoded; i++) {
					if (i != -1) {
						label1 = label1.concat(tokens[i] + " ");
					}
					String label2 = "";
					for (int j = tokens.length; j > i + 1 && !decoded; j--) {

						if (j != tokens.length) {
							label2 = tokens[j].concat(" " + label2);
						}
						currLabel = label1.concat(label2.trim()).trim();

						start = userInput
								.substring(0,
										userInput.lastIndexOf(label2.trim()))
								.replaceFirst(label1, "").trim();

						try {
							determineDateAndTime(start, "start");
							decoded = true;
							decodedOnce = true;
						} catch (WrongTimeFormatException e) {
							decoded = false;
						}
					}
				}

				if (decoded) {
					labelDecoded = currLabel;
					userInput = currLabel;
				} 
			} while (decodedOnce && decoded);
		}
		
		return labelDecoded;

	}

	private void createDeadlineEvent(String userInput) {

		String userInputCopy = userInput;

		boolean decoded = false;
		boolean decodedOnce = false;
		String deadline;
		String currLabel = "";

		userInput = userInput.replaceFirst("(?i)by |(?i)before |(?i)due |(?i)deadline ", "")
				.replaceAll(" +", " ");
		
		do {
			if(userInput.isEmpty()){
				break;
			}
			decoded = false;
			String[] tokens = userInput.replaceAll(" +", " ").split(" ");
			String label1 = "";

			for (int i = -1; i < tokens.length && !decoded; i++) {
				if (i != -1) {
					label1 = label1.concat(tokens[i] + " ");
				}
				String label2 = "";
				for (int j = tokens.length; j > i + 1 && !decoded; j--) {

					if (j != tokens.length) {
						label2 = tokens[j].concat(" " + label2);
					}
					currLabel = label1.concat(label2).trim();

					deadline = " ".concat(userInput
							.substring(0, userInput.lastIndexOf(label2.trim()))
							.replaceFirst(label1, "").trim());

					try {
						determineDateAndTime(deadline, "deadline");
						decoded = true;
						decodedOnce = true;
					} catch (WrongTimeFormatException e) {
						decoded = false;
					}
				}
			}
			
			userInput = currLabel;
			if(decoded){
				label = currLabel;
			}
		} while (decodedOnce && decoded);
		
		if (!decodedOnce){
			eventType = EventType.SCHEDULED;
			createScheduledEvent(userInputCopy);
		}
	}

	public void determineDateAndTime(String dateAndTime, String type)
			throws WrongTimeFormatException {
		String[] tokens;
		String[] TD = { "", ""};

		if (" ".concat(dateAndTime).toLowerCase().contains(" on ")) {
			tokens = " ".concat(dateAndTime).split(" (?i)on ");
			if (tokens[0].trim().isEmpty()) {
				determineDateAndTime(tokens[1].trim(), type);
				return;
			} else {
				try {
					TD[TIME] = TimeUtility.parseTime(tokens[0].trim());
					TD[DATE] = TimeUtility.parseDate(tokens[1].trim());
				} catch (WrongTimeFormatException e) {
					TD[DATE] = TimeUtility.parseDate(tokens[0].trim());
					TD[TIME] = setDefaultTime(type, TD[DATE]);
				}
			}
		} else if (" ".concat(dateAndTime).toLowerCase().contains(" at ")) {
			tokens = " ".concat(dateAndTime).split(" (?i)at ");
			if (tokens[0].trim().isEmpty()) {
				determineDateAndTime(tokens[1].trim(), type);
				return;
			} else {
				try {
					TD[TIME] = TimeUtility.parseTime(tokens[0].trim());
					TD[DATE] = TimeUtility.parseDate(tokens[1].trim());
				} catch (WrongTimeFormatException e) {
					TD[DATE] = TimeUtility.parseDate(tokens[0].trim());
					TD[TIME] = TimeUtility.parseTime(tokens[1].trim());
				}
			}
		} else {
			tokens = dateAndTime.trim().split(" ");
			if (tokens.length == 1) {
				decodeSingleTDwithPrediction(type, tokens, TD);

			} else if (tokens.length == 2) {
				try {
					TD[DATE] = TimeUtility.parseDate(dateAndTime);
					TD[TIME] = setDefaultTime(type, TD[DATE]);
				} catch (WrongTimeFormatException e1) {
					decodeDTwithPrediction(type, tokens, TD);
				}
			} else if(tokens.length==3){
				try {
					TD[DATE] = TimeUtility.parseDate(dateAndTime);
					TD[TIME] = setDefaultTime(type, TD[DATE]);
				} catch (WrongTimeFormatException e1) {
					decodeDTwithDMwithPrediction(dateAndTime, type, tokens, TD);
				}
			}else{
				decodeDTwithDMwithPrediction(dateAndTime, type, tokens, TD);
			}
		}
		up.updateUserPreference();
		assignStartOrEnd(type, TD);
	}

	private void assignStartOrEnd(String type, String[] TD) {
		switch (type) {
		case "start":
			startTime = TD[TIME];
			startDate = TD[DATE];
			break;
		case "end":
		case "deadline":
			endTime = TD[TIME];
			endDate = TD[DATE];
		default:
		}
	}

	private void decodeDTwithDMwithPrediction(String dateAndTime, String type,
			String[] tokens, String[] TD)
			throws WrongTimeFormatException {
		boolean isCorrectPrediction;
		if (up.isDateFirstPrediction()) {

			isCorrectPrediction = dateFirstPreferedDecodingWithDDMM(
					dateAndTime, type, tokens, TD);
			up.updateAfterDateFirstPrediction(isCorrectPrediction);
		} else {
			isCorrectPrediction = timeFirstPreferedDecodingWithDDMM(
					dateAndTime, type, tokens, TD);
			up.updateAfterTimeFirstPrediction(isCorrectPrediction);
		}
	}

	private void decodeDTwithPrediction(String type, String[] tokens,
			String[] TD)
			throws WrongTimeFormatException {
		boolean isCorrectPrediction;
		if (up.isDateFirstPrediction()) {

			isCorrectPrediction = dateFirstPreferedDecoding(type, tokens, TD);
			up.updateAfterDateFirstPrediction(isCorrectPrediction);
		} else {
			isCorrectPrediction = timeFirstPreferedDecoding(type, tokens, TD);
			up.updateAfterTimeFirstPrediction(isCorrectPrediction);
		}
	}

	private void decodeSingleTDwithPrediction(String type, String[] tokens,
			String[] TD)
			throws WrongTimeFormatException {
		
		boolean isCorrectPrediction;
		if (up.isDateOnlyPrediction()) {

			isCorrectPrediction = dateOnlyPreferedDecoding(type, tokens, TD);
			up.updateAfterDateOnlyPrediction(isCorrectPrediction);
		} else {
			isCorrectPrediction = timeOnlyPreferedDecoding(type, tokens, TD);
			up.updateAfterTimeOnlyPrediction(isCorrectPrediction);
		}
		
		if(type.equals("start")){
			validateStartDate();
		}
	}

	private boolean timeFirstPreferedDecodingWithDDMM(String dateAndTime,
			String type, String[] tokens, String[] TD) throws WrongTimeFormatException {
		boolean isCorrectPrediction = true;
		try {
			TD[TIME] = TimeUtility.parseTime(tokens[0]);
			TD[DATE] = TimeUtility
					.parseDate(dateAndTime.replace(tokens[0], ""));

			String date = null, time = null;
			try {
				date = TimeUtility.parseDate(dateAndTime.replace(
						tokens[tokens.length - 1], ""));
				time = TimeUtility.parseTime(tokens[tokens.length - 1]);
			} catch (WrongTimeFormatException e) {
				isCorrectPrediction = true;
			}
			if (!isCorrectPrediction) {
				String message = "Press enter key if the "
						+ type + " time is: " + TD[DATE] + " "
						+ TD[TIME] + "\nIf not, enter \"x\"";
				isCorrectPrediction = chooseCorrectDecodingFromUserFeedback(TD,
						date, time, message);
			}
		} catch (WrongTimeFormatException e2) {
			TD[DATE] = TimeUtility.parseDate(dateAndTime.replace(
					tokens[tokens.length - 1], ""));
			TD[TIME] = TimeUtility.parseTime(tokens[tokens.length - 1]);
			isCorrectPrediction = false;
		}
		return isCorrectPrediction;
	}

	private boolean dateFirstPreferedDecodingWithDDMM(String dateAndTime,
			String type, String[] tokens, String[] TD) throws WrongTimeFormatException {
		boolean isCorrectPrediction = true;
		
		try {
			TD[DATE] = TimeUtility.parseDate(dateAndTime.replace(
					tokens[tokens.length - 1], ""));
			TD[TIME] = TimeUtility.parseTime(tokens[tokens.length - 1]);

			String date = null, time = null;
			try {
				date = TimeUtility.parseTime(tokens[0]);
				time = TimeUtility.parseDate(dateAndTime.replace(
						tokens[0], ""));
			} catch (WrongTimeFormatException e) {
				isCorrectPrediction = true;
			}
			if (!isCorrectPrediction) {
				String message = "Press enter key if the "
						+ type + " time is: " + TD[DATE] + " "
						+ TD[TIME] + "\nIf not, enter \"x\"";
				String feedback = UserInterface
						.displayAndAskForFeedback(message);

				if (feedback.trim().equals("x")) {

					TD[TIME] = date;
					TD[DATE] = time;
					isCorrectPrediction = false;
				}else{
					isCorrectPrediction = true;
				}
			}
		} catch (WrongTimeFormatException e2) {
			TD[TIME] = TimeUtility.parseTime(tokens[0]);
			TD[DATE] = TimeUtility
					.parseDate(dateAndTime.replace(tokens[0], ""));
			isCorrectPrediction = false;
		}
		return isCorrectPrediction;
	}

	private boolean timeFirstPreferedDecoding(String type, String[] tokens,
			String[] TD)
			throws WrongTimeFormatException {
		boolean isCorrectPrediction = false;
		try {
			TD[DATE] = TimeUtility.parseDate(tokens[1]);
			TD[TIME] = TimeUtility.parseTime(tokens[0]);

			String date = null, time = null;
			try {
				date = TimeUtility.parseDate(tokens[0]);
				time = TimeUtility.parseTime(tokens[1]);
			} catch (WrongTimeFormatException e) {
				isCorrectPrediction = true;
			}
			if (!isCorrectPrediction) {
				
				String message = "Press enter key if the "
						+ type + " time is: " + TD[DATE] + " "
						+ TD[TIME] + "\nIf not, enter \"x\"";

				isCorrectPrediction = chooseCorrectDecodingFromUserFeedback(TD,
						date, time, message);
			}
		} catch (WrongTimeFormatException e2) {
			TD[DATE] = TimeUtility.parseDate(tokens[0]);
			TD[TIME] = TimeUtility.parseTime(tokens[1]);
			isCorrectPrediction = false;
		}
		return isCorrectPrediction;
	}

	private boolean dateFirstPreferedDecoding(String type, String[] tokens,
			String[] TD)
			throws WrongTimeFormatException {
		boolean isCorrectPrediction = false;
		try {
			TD[DATE] = TimeUtility.parseDate(tokens[0]);
			TD[TIME] = TimeUtility.parseTime(tokens[1]);

			String date = null, time = null;
			try {
				date = TimeUtility.parseDate(tokens[1]);
				time = TimeUtility.parseTime(tokens[0]);
			} catch (WrongTimeFormatException e) {
				isCorrectPrediction = true;
			}
			if (!isCorrectPrediction) {
				String message = "Press enter key if the "
						+ type + " time is: " + TD[DATE] + " "
						+ TD[TIME] + "\nIf not, enter \"x\"";
				isCorrectPrediction = chooseCorrectDecodingFromUserFeedback(TD,
						date, time, message);
			}
		} catch (WrongTimeFormatException e2) {
			TD[DATE] = TimeUtility.parseDate(tokens[1]);
			TD[TIME] = TimeUtility.parseTime(tokens[0]);
			isCorrectPrediction = false;
		}
		return isCorrectPrediction;
	}

	private boolean dateOnlyPreferedDecoding(String type, String[] tokens,
			String[] TD)
			throws WrongTimeFormatException {
		boolean isCorrectPrediction = false;

		try {
			TD[DATE] = TimeUtility.parseDate(tokens[0]);
			TD[TIME] = setDefaultTime(type,TD[DATE]);

			String date = null, time = null;
			try {
				date = setDefaultDate(type);
				time = TimeUtility.parseTime(tokens[0]);
			} catch (WrongTimeFormatException e) {
				isCorrectPrediction = true;
			}

			if (!isCorrectPrediction) {
				String message = "Press enter key if the "
						+ type + " time is: " + TD[DATE]  + "\nIf not, enter \"x\"";
				isCorrectPrediction = chooseCorrectDecodingFromUserFeedback(TD,
						date, time, message);
			}
		} catch (WrongTimeFormatException e) {
			TD[DATE] = setDefaultDate(type);
			TD[TIME] = TimeUtility.parseTime(tokens[0]);
			isCorrectPrediction = false;
		}
		return isCorrectPrediction;
	}

	

	private boolean timeOnlyPreferedDecoding(String type, String[] tokens,
			String[] TD)
			throws WrongTimeFormatException {
		boolean isCorrectPrediction = false;
		try {
			TD[DATE] = setDefaultDate(type);
			TD[TIME] = TimeUtility.parseTime(tokens[0]);

			String date = null, time = null;
			try {
				date = TimeUtility.parseDate(tokens[0]);
				time = setDefaultTime(type,TD[DATE]);
			} catch (WrongTimeFormatException e) {
				isCorrectPrediction = true;
			}
			if (!isCorrectPrediction) {
				String message = "Press enter key if the "
						+ type + " time is: " + TD[TIME] + "\nIf not, enter \"x\"";
				isCorrectPrediction = chooseCorrectDecodingFromUserFeedback(TD,
						date, time, message);
			}
		} catch (WrongTimeFormatException e) {
			TD[DATE] = TimeUtility.parseDate(tokens[0]);
			TD[TIME] = setDefaultTime(type,TD[DATE]);
			isCorrectPrediction = false;
		}
		return isCorrectPrediction;
	}

	private boolean chooseCorrectDecodingFromUserFeedback(String[] TD,
			String date, String time, String message) {
		boolean isCorrectPrediction;
		String feedback = UserInterface
				.displayAndAskForFeedback(message);
		if (feedback.trim().equals("x")) {
			TD[DATE] = date;
			TD[TIME] = time;
			isCorrectPrediction = false;
		}else{
			isCorrectPrediction = true;
		}
		return isCorrectPrediction;
	}

	private String setDefaultTime(String type, String date) {
		String Time;

		switch (type) {
		case "start":
			if (startTime == null || startTime.isEmpty()) {
				if (date != null && date.trim().equals(TimeUtility.getToday().trim())) {
					Time = TimeUtility.getDateAndTime().replaceAll(
							TimeUtility.getToday(), "");
				} else {
					Time = "00:00";
				}
			} else {
				Time = startTime;
			}
			break;
		default:
			if (endTime == null || endTime.isEmpty()) {
				Time = "23:59";
			} else {
				Time = endTime;
			}
		}
		return Time;
	}
	
	private String setDefaultDate(String type) {
		String date;
		
		switch(type){
		case "start":
			if(startDate==null||startDate.isEmpty()){
				date = endDate;
			}else{
				date = startDate;
			}
			break;
		default:
			if(endDate==null||endDate.isEmpty()){
				date = startDate;
			}else{
				date = endDate;
			}
		}
		
		if(date==null||date.isEmpty()){
			date = TimeUtility.getToday();
		}
		return date;
	}

	private void createTodoEvent(String userInput) {
		label = userInput;
	}

	public String toString() {
		switch (eventType) {
		case SCHEDULED:
			return (label + " from " + startDate + " " + startTime + " to "
					+ endDate + " " + endTime + " " + eventStatus);
		case DEADLINE:
			return (label + " by " + endDate + " " + endTime + " " + eventStatus);
		case TODO:
			return label + " " + eventStatus;
		default:
		}
		return null;
	}

	
}
